package agent;

import java.util.ArrayList;

import model.Coordenada;
import model.Rota;
import model.Shape;
import model.Stop;
import model.SubRota;
import dao.DaoAgente;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;

public class CpBuscaRota extends Behaviour{
	
	ArrayList<Rota> rotas;
	ArrayList<Rota> rotasOk;
	ArrayList<SubRota> subRotas;
	private Coordenada origem;
	private Coordenada destino;
	private Stop stopOrigem;
//	private int raioOrigem;
//	private int raioDestino;
	
	public CpBuscaRota(Agent agente, Coordenada origem, Coordenada destino, Stop stopOrigem){
		super(agente);
		rotas = new ArrayList<Rota>();
		rotasOk = new ArrayList<Rota>();
		subRotas = new ArrayList<SubRota>();
		stopOrigem = new Stop();
		this.origem = origem;
		this.destino = destino;
	}
	
	
	
	@Override
	public void action() {
		System.out.println("Exec comportamento...bUSCA ROTA"+myAgent.getName());
		rotasOk = buscar(origem, destino, subRotas);
		AreaRotas.setRotas(rotasOk);
//		block();
	}

	@Override
	public boolean done() {
		if(AreaRotas.getNumRotas() > 10){
			return true;
		}
		
		return false;
	}
	
	public ArrayList<Rota> buscar(Coordenada origem, Coordenada destino, ArrayList<SubRota> subRotas){
		
		//int raioOrigem = 0;
		int raioDestino = 0;
		int raioShape = 0;
		ArrayList<Stop> stopsOrigem = new ArrayList<Stop>();
		ArrayList<Stop> stopsDestino = new ArrayList<Stop>();
		ArrayList<Shape> forma = new ArrayList<Shape>();
		ArrayList<String> trips = new ArrayList<String>();
		Stop stopDestino = new Stop();
		Shape shapeOrigem = new Shape();
		Shape shapeDestino = new Shape();
		SubRota srt = new SubRota();
		Rota rota = new Rota();
		boolean raioDestinoTocou = false;
		DaoAgente dao = new DaoAgente();
		double distDestOrig = destino.calculaDistancia(origem.getLat(), origem.getLon());
		
			
		//pegando pontos no raio de origem (aumentando o raio de origem até encontrar)
//		while(stopsOrigem.size() == 0){
//			raioOrigem++;
//			stopsOrigem = dao.getStopsOfCoordRaio(origem.getLat(), origem.getLon(), raioOrigem);
//			
//			/*VERIFICAR SE A DISTANCIA À PÉ DO STOP ENCONTRADO PARA ORIGEM É SUPERIOR A DISTÂNCIA À PE ENTRE ORIGEM E DESTINO!!!!*/
//			
//		}
		
		//pegando viagens, testando o primeiro ponto com raio de destino (aumentando o raio de destino até encontrar)
		
		//for(int i = 0; i < stopsOrigem.size(); i++){
		
		
		//Aumentando raio de destino para encontrar as viagens
		while(trips.size() == 0){
			
			raioDestino++;
			trips = dao.getTripsOfStopCoordRaio(stopsOrigem.get(0).getStop_id(), destino.getLat(), destino.getLon(), raioDestino);
		}
			
		for(int t = 0; t < trips.size(); t++){
			if(raioDestinoTocou)
				break;
			stopOrigem = dao.getStopOfTripStopId(trips.get(t), stopsOrigem.get(0).getStop_id());
					
			//pegando stops no destino, da viagem de indice t
			stopsDestino = dao.getStopsOfCoordRaio(trips.get(t), destino.getLat(), destino.getLon(), raioDestino);
			
			
			//testando se raio tocou
			for(int i = 0; i < stopsDestino.size(); i++){
				if(stopOrigem.getStop_id() == stopsDestino.get(i).getStop_id()){
					raioDestinoTocou = true;
					break;
				}
			}
			
			if(raioDestinoTocou)
				break;
			
						
			//eliminando os stops do destino de direção contraria
			ArrayList<Stop> stopsDestinoTemp = new ArrayList<Stop>();
			for(int i = 0; i < stopsDestino.size(); i++){
				if(stopOrigem.getStop_sequence() < stopsDestino.get(i).getStop_sequence()){
					stopsDestinoTemp.add(stopsDestino.get(i));
				}
			}
			if(stopsDestinoTemp.size() == 0){
				continue;
			}
			else{
				stopsDestino = stopsDestinoTemp;
				//identificando o stop mais próximo do destino
				stopDestino = stopsDestino.get(0);
				double distStopDestino;
				double distStopDestinoTeste;
				for(int i = 0; i < stopsDestino.size(); i++){
					distStopDestino = destino.calculaDistancia(stopDestino.getStop_lat(), stopDestino.getStop_lon());
					distStopDestinoTeste = destino.calculaDistancia(stopsDestino.get(i).getStop_lat(), stopsDestino.get(i).getStop_lon());
					if(distStopDestinoTeste < distStopDestino){
						stopDestino = stopsDestino.get(i);
					}
				}
				double distDestStDest = destino.calculaDistancia(stopDestino.getStop_lat(), stopDestino.getStop_lon());
				if(distDestStDest > distDestOrig){
					break;
				}
							
				///Aqui já tenho "stopOrigem" e "stopDestino" com linha viagem.
				
				
				///buscando Shapes de origem
				ArrayList<Shape> shapesOrigem = new ArrayList<Shape>();
				for(raioShape = 1; shapesOrigem.size() == 0; raioShape++){
					shapesOrigem = dao.getShapesOfTripCoordRaio(trips.get(t), stopOrigem.getStop_lat(), stopOrigem.getStop_lon(), raioShape);
				}
				
				//encontrando shape mais pròximo do stop de Origem
				Coordenada coordStopOrig = new Coordenada(stopOrigem.getStop_lat(), stopOrigem.getStop_lon());
				shapeOrigem = shapesOrigem.get(0);
				double distShapeOrigem;
				double distShapeOrigemTeste;
				for(int i = 0; i < shapesOrigem.size(); i++){
					distShapeOrigem = coordStopOrig.calculaDistancia(shapeOrigem.getShape_pt_lat(), shapeOrigem.getShape_pt_lon());
					distShapeOrigemTeste = coordStopOrig.calculaDistancia(shapesOrigem.get(i).getShape_pt_lat(), shapesOrigem.get(i).getShape_pt_lon());
					if(distShapeOrigemTeste < distShapeOrigem){
						shapeOrigem = shapesOrigem.get(i);
					}
				}
				
				
				
				///buscando Shapes de Destino
				ArrayList<Shape> shapesDestino = new ArrayList<Shape>();
				for(raioShape = 1; shapesDestino.size() == 0; raioShape++){
					shapesDestino = dao.getShapesOfTripCoordRaio(trips.get(t), stopDestino.getStop_lat(), stopDestino.getStop_lon(), raioShape);
				}
				
				//encontrando shape mais pròximo do stop de Destino
				Coordenada coordStopDest = new Coordenada(stopDestino.getStop_lat(), stopDestino.getStop_lon());
				shapeDestino = shapesDestino.get(0);
				double distShapeDestino;
				double distShapeDestinoTeste;
				for(int i = 0; i < shapesDestino.size(); i++){
					distShapeDestino = coordStopDest.calculaDistancia(shapeDestino.getShape_pt_lat(), shapeDestino.getShape_pt_lon());
					distShapeDestinoTeste = coordStopDest.calculaDistancia(shapesDestino.get(i).getShape_pt_lat(), shapesDestino.get(i).getShape_pt_lon());
					if(distShapeDestinoTeste < distShapeDestino){
						shapeDestino = shapesDestino.get(i);
					}
				}
				
				///Aqui já tenho "shapeOrigem" e "shapeDestino" com linha viagem.
				
				
				//buscando forma da subrota para ser desenhada
				if(shapeOrigem.getShape_id() == shapeDestino.getShape_id()){
					forma = dao.getShapesOfTripOrigemDestino(shapeOrigem.getShape_id(), shapeOrigem.getShape_pt_sequence(), shapeDestino.getShape_pt_sequence());
				}
				else{
					System.out.println("SHAPE DE ORIGEM DIFERENTE DO SHAPE DE DESTINO!!!!!");
				}
				
				//Montando SubRota
				srt.setForma(forma);
				srt.setStopOrigem(stopOrigem);
				srt.setStopDestino(stopDestino);
				srt = dao.preencheSubrota(trips.get(t), srt);
				subRotas.add(srt);
				
				if(raioDestino <= 2){
					rota.setSubrotas(subRotas);
					this.rotas.add(rota);
					return rotas;
				}
				else{
				//recurção
					Coordenada novaOrigem = new Coordenada(stopDestino.getStop_lat(), stopDestino.getStop_lon());
					System.out.println("Recurção");
					buscar(novaOrigem, destino, subRotas);
				}
				
			}
			
		}
		rota.setSubrotas(subRotas);
		this.rotas.add(rota);
		return rotas;
			
	}
	
	
	
	
	public boolean toucouRaio(ArrayList<String> trips, double lat, double lon, int raioDestino, Stop stopOrigem){
		boolean tocaRaio = false;
		DaoAgente dao = new DaoAgente();
		//pegando stops no destino, da viagem de indice t
		for(int t = 0; t < trips.size(); t++){
			ArrayList<Stop> stopsDestino = dao.getStopsOfCoordRaio(trips.get(t), destino.getLat(), destino.getLon(), raioDestino);
			
			//Verificando se o raio destino tocou o stopOrigem
			for(int i = 0; i < stopsDestino.size(); i++){
				
				if((stopOrigem.getStop_lat() == stopsDestino.get(i).getStop_lat()) && (stopOrigem.getStop_lon() == stopsDestino.get(i).getStop_lon())){
					tocaRaio = true;
				}
				
			}
			if(tocaRaio){
				return tocaRaio;
			}
		}
		return tocaRaio;
		
	}
	
	//gets e sets
		public ArrayList<Rota> getRotas() {
			return rotas;
		}

		public void setRotas(ArrayList<Rota> rotas) {
			this.rotas = rotas;
		}
		
	
}
	
	


